package com.dongzili.easyes.common.mybatisplus;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class MybatisPlusUtil {
    /**
     * Service服务缓存
     */
    private static final ConcurrentHashMap<Class<?>, IService<?>> SERVICE_CACHE = new ConcurrentHashMap<>();

    /**
     * Mapper缓存
     */
    private static final ConcurrentHashMap<Class<?>, BaseMapper<?>> MAPPER_CACHE = new ConcurrentHashMap<>();

    /**
     * 获取Service（带缓存）
     */
    @SuppressWarnings("unchecked")
    public static <T> IService<T> getService(final Class<T> t) {
        try {
            return (IService<T>) SERVICE_CACHE.computeIfAbsent(t, k -> {
                String beanName = getBeanName(t) + "AutoServiceImpl";
                return SpringUtil.getBean(beanName);
            });
        } catch (NoSuchBeanDefinitionException e) {
            throw new RuntimeException("未找到对应的Service实现: " + getBeanName(t) + "AutoServiceImpl", e);
        }
    }


    /**
     * 获取Mapper（带缓存）
     */
    @SuppressWarnings("unchecked")
    public static <T> BaseMapper<T> getMapper(final Class<T> t) {
        try {
            return (BaseMapper<T>) MAPPER_CACHE.computeIfAbsent(t, k -> {
                String beanName = getBeanName(t) + "AutoMapper";
                return SpringUtil.getBean(beanName);
            });
        } catch (NoSuchBeanDefinitionException e) {
            throw new RuntimeException("未找到对应的Mapper: " + getBeanName(t) + "AutoMapper", e);
        }
    }



    /**
     * 获取bean名称
     */
    private static <T> String getBeanName(final Class<T> t) {
        return t.getSimpleName().substring(0, 1).toLowerCase() + t.getSimpleName().substring(1);
    }


    public static <T> String getMapperName(final Class<T> t) {
        try {
            BaseMapper<T> mapper = getMapper(t);
            return getMapperClassName(mapper);
        } catch (NoSuchBeanDefinitionException e) {
            throw new RuntimeException("未找到对应的Mapper: " + getBeanName(t) + "AutoMapper", e);
        }
    }
    /**
     * 获取BaseMapper实例对应的实际实现类全名
     * @param mapper BaseMapper实例
     * @return 实际实现类全名，若无法获取则返回null
     */
    public static String getMapperClassName(BaseMapper<?> mapper) {
        if (mapper == null) {
            return null;
        }

        // MyBatis的Mapper是通过JDK动态代理实现的
        if (Proxy.isProxyClass(mapper.getClass())) {
            try {
                // 获取代理对象中的h字段（InvocationHandler）
                Field hField = mapper.getClass().getSuperclass().getDeclaredField("h");
                hField.setAccessible(true);
                Object invocationHandler = hField.get(mapper);

                // 获取InvocationHandler中的target字段（实际的Mapper实现）
                Field targetField = invocationHandler.getClass().getDeclaredField("mapperInterface");
                targetField.setAccessible(true);
                Object target = targetField.get(invocationHandler);

                Field nameField = target.getClass().getDeclaredField("name");
                nameField.setAccessible(true);
                Object name = nameField.get(target);
                // 返回实际实现类的全名
                return name.toString();
            } catch (Exception e) {
                // 如果反射失败，返回代理类名
                return mapper.getClass().getName();
            }
        }

        // 非代理对象直接返回类名
        return mapper.getClass().getName();
    }
}